﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WMemoryProfiler;
using WMemoryProfiler.Memory;
using System.Diagnostics;
using System.Threading;

namespace AllocateManyObjects
{
    /// <summary>
    /// Shows the basic usage of WMemoryProfiler
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if( args.Length > 0 )
                {
                    Console.WriteLine("Wait for debugger to attach");
                    Console.ReadLine();
                    return;
                }
                        
                // Start this application not under the debugger
                // To start is press Ctrl+F5 in Visual Studio to start it without debugging.
                 GetStatsFromOtherProcess();
                 SelfDebug();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Got Exception: {0}", ex);
            }
            Console.WriteLine("Press Enter to exit.");
            Console.ReadLine();
        }




        /// <summary>
        /// Get memory stats from other process
        /// </summary>
        private static void GetStatsFromOtherProcess()
        {
            // start ourself
            var p = Process.Start(Process.GetCurrentProcess().MainModule.FileName.Replace(".vshost", ""), "-Other");

            using (var debugger = new MdbEng(p.Id, ProcessWindowStyle.Normal))
            {
                var stats = debugger.GetMemoryState();
                Console.WriteLine("{0} types with {1} instances", stats.Count, stats.Aggregate(0, (sum, x) => sum + x.Value.InstanceCount));
            }

            // Kill process in the right way. First we do terminate the process
            // and then wait for on the process handle until the process has terminated since process
            // termination is asychronous. Unfortunately .NET does close the process handle immediately which makes
            // it impossible to wait until a process was really shut down.
            NativeMethods.TerminateProcess(p.Handle, 99);
            p.WaitForExit();
        }

        /// <summary>
        /// Issue a !Threads command and print the output to console
        /// </summary>
        private static void SelfDebug()
        {
            using (var debugger = new MdbEng())
            {
                string[] output = debugger.Execute("!Threads");
                Console.WriteLine(String.Join(Environment.NewLine, output));
            }
        }

        static List<string> strs = new List<string>();
        private static List<string> Allocate()
        {
            for (int i = 0; i < 1000; i++)
            {
                strs.Add("String data: " + i.ToString());
            }

            return strs;
        }
    }
}
